package com.etl.sys.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eksframework.commons.core.base.EksCheck;
import com.eksframework.commons.core.base.EksCopier;
import com.eksframework.commons.json.EksJson;
import com.etl.sys.entity.*;
import com.etl.sys.service.*;
import com.etl.sys.vo.ScheduleParam;
import com.etl.sys.vo.ScheduleVO;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 调度表 前端控制器
 * </p>
 *
 * @author chenfenghai
 * @since 2020-11-03
 */
@Slf4j
@RestController
@RequestMapping("/schedule")
public class SysScheduleController {

    @Autowired
    ISysTenantService sysTenantService;
    @Autowired
    ISysCinemaService sysCinemaService;
    @Autowired
    ISysModuleService sysModuleService;
    @Autowired
    ISysDatabaseService sysDatabaseService;
    @Autowired
    ISysTaskService sysTaskService;
    @Autowired
    ISysScheduleService sysScheduleService;

    @PostMapping("/page")
    public IPage<ScheduleVO> page(@RequestBody ScheduleParam params) {
        log.debug("page: {}", EksJson.toJson(params));
        QueryWrapper<SysSchedule> queryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(params.getCinemaId()) && params.getCinemaId() > 0) {
            queryWrapper.eq("CINEMA_ID", params.getCinemaId());
        }
        if (Objects.nonNull(params.getDatabaseId()) && params.getDatabaseId() > 0) {
            queryWrapper.eq("DATABASE_ID", params.getDatabaseId());
        }
        if (Objects.nonNull(params.getModuleId()) && params.getModuleId() > 0) {
            queryWrapper.eq("MODULE_ID", params.getModuleId());
        }
        if (Objects.nonNull(params.getTaskId()) && params.getTaskId() > 0) {
            queryWrapper.eq("TASK_ID", params.getTaskId());
        }
        IPage<SysSchedule> page = new Page<>(
                params.getPageNumber(), params.getPageSize(), params.getTotal());
        page = sysScheduleService.page(page, queryWrapper);
        if (EksCheck.isEmpty(page.getRecords())) {
            return new Page<>(params.getPageNumber(), params.getPageSize(), params.getTotal());
        }
        List<Long> cinemaIdList = page.getRecords().stream()
                .map(SysSchedule::getCinemaId).distinct().collect(Collectors.toList());
        Map<Long, SysCinema> cinemaMap = sysCinemaService.listByIds(cinemaIdList).stream()
                .collect(Collectors.toMap(SysCinema::getCinemaId, Function.identity()));
        List<Long> tenantIdList = cinemaMap.values().stream()
                .map(SysCinema::getTenantId).distinct().collect(Collectors.toList());
        Map<Long, SysTenant> tenantMap = sysTenantService.listByIds(tenantIdList).stream()
                .collect(Collectors.toMap(SysTenant::getTenantId, Function.identity()));
        List<Long> moduleIdList = page.getRecords().stream()
                .map(SysSchedule::getModuleId).distinct().collect(Collectors.toList());
        Map<Long, SysModule> moduleMap = sysModuleService.listByIds(moduleIdList).stream()
                .collect(Collectors.toMap(SysModule::getModuleId, Function.identity()));
        List<Long> taskIdList = page.getRecords().stream()
                .map(SysSchedule::getTaskId).distinct().collect(Collectors.toList());
        Map<Long, SysTask> taskMap = sysTaskService.listByIds(taskIdList).stream()
                .collect(Collectors.toMap(SysTask::getTaskId, Function.identity()));
        List<Long> databaseIdList = page.getRecords().stream()
                .map(SysSchedule::getDatabaseId).distinct().collect(Collectors.toList());
        if (EksCheck.isEmpty(databaseIdList)) {
            databaseIdList.add(0L);
        }
        Map<Long, SysDatabase> databaseMap = sysDatabaseService.listByIds(databaseIdList).stream()
                .collect(Collectors.toMap(SysDatabase::getDatabaseId, Function.identity()));
        return page.convert(sysSchedule -> {
            ScheduleVO scheduleVO = EksCopier.copy(sysSchedule, ScheduleVO.class);
            SysCinema sysCinema = cinemaMap.get(sysSchedule.getCinemaId());
            EksCopier.copy(sysCinema, scheduleVO);
            EksCopier.copy(tenantMap.get(sysCinema.getTenantId()), scheduleVO);
            EksCopier.copy(moduleMap.get(sysSchedule.getModuleId()), scheduleVO);
            EksCopier.copy(taskMap.get(sysSchedule.getTaskId()), scheduleVO);
            if (EksCheck.notNull(sysSchedule.getDatabaseId())
                    && databaseMap.containsKey(sysSchedule.getDatabaseId())) {
                scheduleVO.setShortName(databaseMap.get(sysSchedule.getDatabaseId()).getShortName());
            }
            return scheduleVO;
        });
    }

    @PostMapping("/save")
    public void save(@Validated @RequestBody ScheduleVO scheduleVO) {
        if (Objects.isNull(scheduleVO.getScheduleId()) || scheduleVO.getScheduleId() <= 0) {
            scheduleVO.setScheduleId(null);
            Integer count = sysScheduleService.lambdaQuery()
                    .eq(SysSchedule::getCinemaId, scheduleVO.getCinemaId())
                    .eq(SysSchedule::getModuleId, scheduleVO.getModuleId())
                    .eq(SysSchedule::getTaskId, scheduleVO.getTaskId())
                    .count();
            if (count > 0) {
                throw new IllegalArgumentException("调度任务不能重复，请重新填写");
            }
        }
        SysSchedule sysSchedule = EksCopier.copy(scheduleVO, SysSchedule.class);
        sysScheduleService.saveOrUpdate(sysSchedule);
    }

    @DeleteMapping("/del")
    public void del(@RequestParam(name = "scheduleId") Long scheduleId) {
        sysScheduleService.lambdaUpdate()
                .set(SysSchedule::getDeleteFlag, scheduleId)
                .eq(SysSchedule::getScheduleId, scheduleId)
                .update();
    }
}
